package ecdsa

import (
	"crypto/ecdsa"
	"osiris/logger"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/common/hexutil"
	ethcrypto "github.com/ethereum/go-ethereum/crypto"
)

// ECDSASign 通过ecdsa签名Keccak256Hash
//
//	@param commonHash 待签名内容的Keccak256Hash
//	@param privKey ecdsa私钥
//	@return []byte 签名
//	@return error
func ECDSASign(commonHash common.Hash, privKey *ecdsa.PrivateKey) ([]byte, error) {
	return ethcrypto.Sign(commonHash.Bytes(), privKey)
}

// ECDSAVerify 通过ecdsa验证签名（为什么不需要公钥：ecdsa能通过签名和被签名的Keccak256Hash推公钥，再根据公钥验证签名）
//
//	@param commonHash 被签名的Keccak256Hash
//	@param signature
//	@return bool 是否通过
func ECDSAVerify(commonHash common.Hash, signature []byte) bool {
	recoverdPubKey, err := recoverECDSAPubKey(commonHash, signature)
	if err != nil {
		logger.Error(map[string]interface{}{"[ocrypto] [ECDSA Verify] recover pubKey": err})
		return false
	}

	return ethcrypto.VerifySignature(ethcrypto.CompressPubkey(recoverdPubKey), commonHash.Bytes(), signature[:len(signature)-1])
}

// ECDSASigToStr ecdsa签名（字节数组）转字符串
//
//	@param sig
//	@return string
func ECDSASigToStr(sig []byte) string {
	return hexutil.Encode(sig)
}

// StrToECDSASig 字符串转ecdsa签名（字节数组）
//
//	@param sigStr
//	@return []byte
//	@return error
func StrToECDSASig(sigStr string) ([]byte, error) {
	return hexutil.Decode(sigStr)
}

// recoverECDSAPubKey 从签名、被签名的hash中恢复公钥
//
//	@param commonHash 被签名的hash
//	@param signature ecdsa签名
//	@return *ecdsa.PublicKey
//	@return error
func recoverECDSAPubKey(commonHash common.Hash, signature []byte) (*ecdsa.PublicKey, error) {
	return ethcrypto.SigToPub(commonHash.Bytes(), signature)
}

// Keccak256Hash 计算Keccak256Hash（common.Hash）
//
//	@param bytes
//	@return common.Hash
func Keccak256Hash(bytes []byte) common.Hash {
	return ethcrypto.Keccak256Hash(bytes)
}

// Keccak256HashToStr Keccak256Hash转字符串
//
//	@param hash
//	@return string
func Keccak256HashToStr(hash common.Hash) string {
	return hash.Hex()
}

// Keccak256HashBytesToStr Keccak256Hash字节数组转字符串
//  @param bytes 
//  @return string 
func Keccak256HashBytesToStr(bytes []byte) string {
	commonHash := Keccak256Hash(bytes)
	return Keccak256HashToStr(commonHash)
}

// StrToKeccak256Hash 字符串转Keccak256Hash
//
//	@param hashString
//	@return common.Hash
func StrToKeccak256Hash(hashString string) common.Hash {
	return common.HexToHash(hashString)
}
